package com.bioscript.standalone.imps;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.bioscript.standalone.UtilMethods;
import com.bioscript.standalone.IO.FileReader;
import com.bioscript.standalone.dataStructures.Generation;
import com.bioscript.standalone.dataStructures.Range;

public class ContigsPreProcessor {

	private String in_fileName; private String out_fileName; private Generation.types gen;
	
	public static void main(String[] args)
	{
		ContigsPreProcessor contigsPreProcessor = new ContigsPreProcessor(args[0], 
				args[1], Generation.types.valueOf(args[2]));
		contigsPreProcessor.process(args.length == 4 ? args[3] : null);
	}
	
	public ContigsPreProcessor(String in_fileName, String out_fileName,Generation.types gen)
	{
		this.in_fileName = in_fileName;
		this.out_fileName = out_fileName;
		this.gen = gen;
	}
	/**
	 * @param in_fileName
	 * @param out_fileName
	 * @param mappingfile
	 * @param gen
	 */
	public boolean process(String mappingfile)
	{
		boolean success = false;
		switch(gen)
		{
		case DeNovo:
			success = enrichDenovo(mappingfile);
			break;
		case Mapped:
			success = enrichMapped();
			break;
		}
		return success;
	}
	
	private boolean enrichMapped() 
	{
		com.bioscript.standalone.IO.FileReader fileReader =
			new com.bioscript.standalone.IO.FileReader();
		try
		{
			PrintWriter pw = new PrintWriter(out_fileName);
			Map<String,List<String>> map = fileReader.contigsFileReader(in_fileName);
			List<String> headers = FileReader.readFastaHeaders(in_fileName);
			if (map.keySet().size() == 0) return false;
			for(String str : headers)
			{
				List<String> lst = map.get(str);
				String[] params = str.replaceAll("\\s+", " ").trim().split(" ");
				List<Integer> dims = calculateDimensions(lst);
				pw.println(params[0] + " " + params[2] + 
						" " + "length=" + dims.get(1) +
						" " + "numreads=" + params[4].split("=")[1] +
						" coverage=-" + " orientation=+ gc=" + dims.get(0));
				for(int i = 0 ; i < lst.size() ; i++)
				{
					pw.println(lst.get(i));
				}
			}
			pw.flush();
			pw.close();
			return true;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return false;
	}
	private boolean enrichDenovo(String mappingFile)
	{
		com.bioscript.standalone.IO.FileReader fileReader =
			new com.bioscript.standalone.IO.FileReader();
		// get the mapped contigs
		List<Range> contigs = fileReader.parseTilingFile2(mappingFile);
		try
		{
			PrintWriter pw = new PrintWriter(out_fileName);
			Map<String,List<String>> map = fileReader.contigsFileReader(in_fileName);
			if (map.keySet().iterator().next().split(" ").length > 1)
			{
				map =reCreateMap(map);
			}
			if (map.keySet().size() == 0) return false;
			for (Range contig : contigs)
			{
				if (map.containsKey(">" + contig.getName()))
				{
					List<String> lst = map.get(">" + contig.getName());
					List<Integer> dims = calculateDimensions(lst);
					pw.println(">" + contig.getName() + " " +
							contig.getLowerLimit() + ".." + contig.getUpperLimit() + 
							" " + "length=" + dims.get(1) +
							" " + "numreads=- coverage=" +
							(contig.getName().split("_").length > 1 ? contig.getName().split("_")[5] : "-")
								+ " orientation=+ gc=" + dims.get(0));
					for(int i = 0 ; i < lst.size() ; i++)
					{
						pw.println(lst.get(i));
					}
				}
			}
			pw.flush();
			pw.close();
			return true;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return false;
	}
	private Map<String, List<String>> reCreateMap(Map<String, List<String>> map) {
		Map<String, List<String>> map2 = new HashMap<String, List<String>>();
		Set<String> keySet = map.keySet();
		for(String str : keySet)
		{
			map2.put(str.split(" ")[0], map.get(str));
		}
		return map2;
	}

	private List<Integer> calculateDimensions(List<String> lst) {
		int gc = 0;
		int size = 0;
		for (String str : lst)
		{
			size = str.trim().length() + size;
			gc = gc + UtilMethods.findGCContent(str);
		}
		List<Integer> result = new ArrayList<Integer>();
		result.add(gc); result.add(size);
		return result;
	}
}
